//
// Maths.cpp for  in /home/goldbe_y//tek3/Projets/Maths/302graphe
// 
// Made by yoni goldberg
// Login   <goldbe_y@epitech.net>
// 
// Started on  Mon Sep 24 14:39:22 2012 yoni goldberg
// Last update Tue Oct 30 16:16:44 2012 yoni goldberg
//

#include "Maths.hpp"

Maths::Maths(const std::string &str)
{
  Parse	tmp(str);
  _dim = tmp.get_dim();
  _matrix = tmp.get_mat();
  _save_m = new float*[_dim];
  for (int i = 0; i < _dim; i++)
    _save_m[i] = new float[_dim];

  for (int i = 0; i < _dim; i++)
    for (int j = 0; j < _dim; j++)
      _save_m[i][j] = _matrix[i][j];

  _vecteur = tmp.get_vecteur();
  for (int i = 0; i < _dim; i++)
    _save_v[i] = _vecteur[i];

  _rep = new float[_dim];
  pivot();
}

Maths::~Maths()
{
}

bool			Maths::is_direct()
{
  for (int i = 1; i < _dim; i++)
    for (int j = 0; j < i; j++)
      if (_matrix[i][j] != 0)
	return false;
  return true;
}

// operation matrice

void			Maths::sub(int a, int b, float mult)
{
  _vecteur[a] -= _vecteur[b] * mult;
  for (int i = 0; i < _dim; i++)
    _matrix[a][i] -= _matrix[b][i] * mult;
}

void			Maths::div(int i, float j)
{
  for (int column = 0; column < _dim; column++)
    _matrix[i][column] /= j;
  _vecteur[i] /= j;
}

// algo de gauss

void			Maths::monte()
{
  _rep[_dim - 1] = _vecteur[_dim - 1] / _matrix[_dim - 1][_dim - 1];
  for (int i = 0; i < _dim; i++)
    for (int j = i; j < _dim; j++)
      div(i, _matrix[i][i]);

  for (int i = 1; i < _dim; i++)
    for (int j = i - 1; j >= 0; j--)
      sub(j , i, _matrix[j][i]);
}

void			Maths::descente()
{
  for (int i = 0; i < _dim - 1; i++)
    for (int j = i + 1; j < _dim; j++)
      sub(j, i, _matrix[j][i] / _matrix[i][i]);
}

void			Maths::pivot()
{
  aff_matrix();
  for (int i = 0; i < _dim; i++)
    if (_matrix[i][i] == 0 && i + 1 < _dim)
      {
	int j = i + 1;
	while (j < _dim && _matrix[j][0] == 0)
	  j++;
	swap<float *>(&_matrix[j], &_matrix[i]);
	swap<float>(&_vecteur[j], &_vecteur[i]);
      }
  if (!is_direct())
    descente();
  monte();
  std::cout << std::endl;
  aff_matrix();
  std::cout << std::endl;
  mult_matrix();
}


// DEBUG


void			Maths::aff_matrix()
{
  for (int i = 0; i < _dim; i++)
    {
      for (int j = 0; j < _dim; j++)
	std::cout << _matrix[i][j] << " ";
      std::cout << std::endl;
    }
}

float			Maths::calc(int line)
{
  float		temp = 0;

  for (int i = 0; i < _dim; i++)
    temp += (_save_m[line][i] * _vecteur[i]);
  return temp;
}

void			Maths::mult_matrix()
{
  float		*temp = new float[_dim];

  for (int line = 0; line < _dim; line++)
    temp[line] = calc(line);


  for (int i = 0; i < _dim; i++)
    std::cout << _vecteur[i] << std::endl;
  std::cout << std::endl;
  for (int i = 0; i < _dim; i++)
    std::cout << temp[i] - _save_v[i] << std::endl;
}
